﻿#region Copyright (c) 2007 Mikko Salmi, Contributors
/*
 *
 * Copyright (c) 2007 Mikko Salmi, Contributors
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
 * 
*/
#endregion // Copyright

using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Xml.Serialization;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Navigation;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.JScript;

namespace CodePlex.WebParts
{
    [XmlRoot(Namespace = "CodePlex.WebParts")]
    [Guid("5B23C91A-03CE-4535-A17B-C237A1778EEA")]
    public class TickerWebPart : AdvancedWebPart
    {
        public TickerWebPart()
        {
            this.ExportMode = WebPartExportMode.All;
        }

        #region Ticker

        string listName;

        [Personalizable(PersonalizationScope.Shared),
        WebBrowsable,
        WebDisplayName("List Name"),
        WebDescription("Name of the list with Ticker items."),
        SPWebCategoryName("Ticker")]
        public string ListName
        {
            get
            {
                return listName;
            }
            set
            {
                listName = value;
            }
        }

        private const string titleFieldNameDefault = "Title";
        string titleFieldName = titleFieldNameDefault;

        [Personalizable(PersonalizationScope.Shared),
        WebBrowsable,
        WebDisplayName("Title Field Name"),
        WebDescription("Name of the column/field that will be displayed as Title in Ticker."),
        SPWebCategoryName("Ticker")]
        public string TitleFieldName
        {
            get
            {
                return titleFieldName;
            }
            set
            {
                titleFieldName = value;
            }
        }

        private const string linkFieldNameDefault = "Link";
        string linkFieldName = linkFieldNameDefault;

        [Personalizable(PersonalizationScope.Shared),
        WebBrowsable,
        WebDisplayName("Link Field Name"),
        WebDescription("Name of the field that will be displayed as Link in Ticker. This field should be normal text field and not a hyperlink one."),
        SPWebCategoryName("Ticker")]
        public string LinkFieldName
        {
            get
            {
                return linkFieldName;
            }
            set
            {
                linkFieldName = value;
            }
        }

        private const string descFieldNameDefault = "Description";
        string descFieldName = descFieldNameDefault;

        [Personalizable(PersonalizationScope.Shared),
        WebBrowsable,
        WebDisplayName("Description Field Name"),
        WebDescription("Name of the field that will be displayed as description of Ticker. Ticker supports Rich HTML."),
        SPWebCategoryName("Ticker")]
        public string DescFieldName
        {
            get
            {
                return descFieldName;
            }
            set
            {
                descFieldName = value;
            }
        }

        private const int delayDefault = 3000;
        int delay = delayDefault;

        [Personalizable(PersonalizationScope.Shared),
        WebBrowsable,
        WebDisplayName("Delay"),
        WebDescription("Delay between message change, milliseconds."),
        SPWebCategoryName("Ticker")]
        public int Delay
        {
            get
            {
                return delay;
            }
            set
            {
                delay = value;
            }
        }

        #endregion // Ticker
       
        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            // Add link to style sheet.
            string styleSheetUrl = SPContext.Current.Web.Url + @"/_layouts/CodePlex/TickerWebPart/Ticker.css";            
            WebPartTools.CreateStyleSheetLink(this.Page, styleSheetUrl);

            // Add link to Dynamic Drive ticker script.
            string scriptUrl = SPContext.Current.Web.Url + @"/_layouts/CodePlex/TickerWebPart/Ticker.js";
            WebPartTools.CreateScriptLink(this.Page, scriptUrl);

            createTickerScript();          
        }

        protected override void Render(HtmlTextWriter writer)
        {
            writer.Write(
                "<script type=\"text/javascript\">new pausescroller(tickerContent" + getTickerNumber() + ", \"ticker" + getTickerNumber() + "\", \"tickerClass\", " + delay.ToString() + " );</script><br/><br/>");           

            base.Render(writer);
        }

        protected string getTickerNumber()
        {
            int i = 1;
            foreach (System.Web.UI.WebControls.WebParts.WebPart part in this.WebPartManager.WebParts)
            {
                if (part.GetType() == typeof(TickerWebPart))
                {
                    if (part.ID == this.ID)
                    {
                        break;
                    }

                    i++;
                }
            }

            return i.ToString();
        }

        private void createTickerScript()
        {
            string tickerContent = getTickerContent();            

            string script = "<script type=\"text/javascript\"> " + Environment.NewLine +
            "var tickerContent" + getTickerNumber() + " = new Array() " + Environment.NewLine +
                 tickerContent + Environment.NewLine +
            "</script>" + Environment.NewLine;
            
            LiteralControl tickerScript = new LiteralControl();
            tickerScript.Text = script;

            if (this.Page.Header != null)
                this.Page.Header.Controls.Add(tickerScript);
        }        

        private string getTickerContent()
        {
            string tickerContent = string.Empty;

            SPWeb web = SPContext.Current.Web;

            try
            {

                int i = 0;
                foreach (SPListItem item in web.Lists[listName].Items)
                {
                    tickerContent +=
                        "tickerContent" + getTickerNumber() + "[" + i + "] = '";

                    if (item.Fields.ContainsField(LinkFieldName))
                        tickerContent += "<a href=\"" + item[LinkFieldName] + "\" target=\"_blank\">";

                    tickerContent += GlobalObject.escape(item[TitleFieldName]);

                    if (item.Fields.ContainsField(LinkFieldName))
                        tickerContent += "</a>";

                    if (item.Fields.ContainsField(DescFieldName))
                        tickerContent += "<br/>" + GlobalObject.escape(item[DescFieldName]);

                    tickerContent += "';" + Environment.NewLine;

                    i++;
                }
                // There is an error in js that shows string "undefined" if there is only 1 item in list. 
                // To get around this, display first item twice when scrolling.
                if (i == 1)
                    tickerContent += tickerContent.Replace("tickerContent" + getTickerNumber() + "[0]", "tickerContent" + getTickerNumber() + "[1]");
            }
            catch (ArgumentException)
            {
                if (string.IsNullOrEmpty(listName))
                    RegisterError("Ticker source list name is not set. Edit web part properties to set correct list name. ");
                else 
                    RegisterError("Ticker source list name: " + listName + " is not found.");
            }

            return tickerContent;
        }
    }
}